<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 传入一个函数,将其改写为柯里化函数 
    // 传入的函数参数可以不受限制
    /* function currying(callback){
        var _args = []; // 用于存放所有参数(闭包)
        return function () { // 
            console.log(arguments); // [1]
            _args.push(...arguments); // Array.prototype.push.apply(_args,arguments);
            if(arguments.length == 0){  // 没有参数 最后一层 => 执行传入的回调函数
                console.log("最后一层",_args);
                // return callback(..._args);  // 如果参数传入完毕 => 调用原函数
                return callback.apply(null,_args);  // 如果参数传入完毕 => 调用原函数
            }
            return arguments.callee;
        }
    }

    function add(){
        var sum = 0;
        for(var i = 0;i<arguments.length;i++){
            var item = arguments[i];
            sum += item;
        }
        return sum;
    }


    var sum = currying(add);
    console.log(sum);


    // 此写法优点 => 传入的参数可以不受长度限制
    // 缺点:  最后要多加一个() => 不传参(arguments.length == 0) => 自动计算
    // var res = sum(1)(2)(3)();   // 三个参数
    // var res = sum(1)(2)(3)(4)(5)(6)();   // 6个参数
    var res = sum(1)(2)();   // 2个参数  =>  a:1  b:2  c:undefined  => NaN
    console.log("res",res); */


    // 优化版 => 期望函数结果不需要多加 () 

    // 回调函数参数限定版(知道要传几个参数)
    // function currying(callback){
    //     var _args = []; // 用于存放所有参数(闭包)
    //     var len = callback.length; // 传入的回调函数需要接收的参数个数
    //     return function () { // 
    //         console.log(arguments); // [1]
    //         _args.push(...arguments); // Array.prototype.push.apply(_args,arguments);
    //         if(_args.length >= len){  // 参数已经够了,多传也没有用 => 执行传入的回调函数
    //             console.log("最后一层",_args);
    //             // return callback(..._args);  // 如果参数传入完毕 => 调用原函数
    //             return callback.apply(null,_args);  // 如果参数传入完毕 => 调用原函数
    //         }
    //         return arguments.callee;
    //     }
    // }

    // // 回调函数参数不限定版(可以传一个或多个)
    // function currying(callback) {
    //     return function () { // 
    //         var _args = [...arguments]; // 用于存放所有参数(闭包)
    //         function func() {
    //             _args.push(...arguments);
    //             return func;
    //         }
    //         // func隐式转字符串时调用   
    //         func.toString = func.valueOf = function () {
    //             console.log("隐式转字符串",_args);
    //             console.log("隐式转字符串",callback(..._args));
    //             return callback(..._args);  // 计算最终的结果
    //             // return callback.apply(null,_args);
    //         }
    //         return func;
    //     }
    // }

    // 整合版

    /* function currying(callback) {
        var len = callback.length; // 传入的回调函数需要接收的参数个数
        if (len > 0) { // 有至少一个参数  => 已知需要接收几个参数
            var _args = []; // 用于存放所有参数(闭包)
            return function () { // 
                console.log(arguments); // [1]
                _args.push(...arguments); // Array.prototype.push.apply(_args,arguments);
                if (_args.length >= len) {  // 参数已经够了,多传也没有用 => 执行传入的回调函数
                    console.log("最后一层", _args);
                    // return callback(..._args);  // 如果参数传入完毕 => 调用原函数
                    return callback.apply(null, _args);  // 如果参数传入完毕 => 调用原函数
                }
                return arguments.callee;
            }
        } else {
            return function () { // 
                var _args = [...arguments]; // 用于存放所有参数(闭包)
                function func() {
                    _args.push(...arguments);
                    return func;
                }
                // func隐式转字符串时调用   
                func.toString = func.valueOf = function () {
                    console.log("隐式转字符串", _args);
                    console.log("隐式转字符串", callback(..._args));
                    return callback(..._args);  // 计算最终的结果
                    // return callback.apply(null,_args);
                }
                return func;
            }
        }
    }
 */

    function currying(callback) {
        var len = callback.length; // 传入的回调函数需要接收的参数个数
        return function () { // 
            var _args = [...arguments]; // 用于存放所有参数(闭包)
            function func() {
                _args.push(...arguments);
                return func;
            }
            // func隐式转字符串时调用   
            func.toString = func.valueOf = function () {
                console.log("隐式转字符串", _args);
                console.log("隐式转字符串", _args.length >= len);
                // console.log(func);
                return _args.length >= len ? callback(..._args) : func;  // 计算最终的结果
                // return callback.apply(null,_args);
            }
            return func;
        }
    }



    function add(a, b, c) {
        // var sum = 0;
        // for (var i = 0; i < arguments.length; i++) {
        //     var item = arguments[i];
        //     sum += item;
        // }
        // return sum;
        return a + b + c;
    }


    var sum = currying(add)
    // console.log(sum);

    var res = sum(1)(2)(3)(4); // res = func
    var res = sum(1)(2)(3); // res = func
    var res = sum(1)(2); // res = func
    // console.log();
    res.toString()







</script>

</html>